package xyz.zhno.project.commons.web.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import xyz.zhno.project.commons.core.exception.ProjectExceptionCodeEnum;
import xyz.zhno.project.commons.core.exception.ProjectJsonException;

import java.util.Map;

/**
 * JSON 工具类
 * @author zh_o
 * @date 2020-11-01
 */
@Slf4j
public class JsonUtils {

    private static final ObjectMapper JSON;

    static {
        JSON = new ObjectMapper();
        // 忽略json中在对象不存在对应属性
        JSON.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 忽略空bean转json错误
        JSON.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }

    /**
     * 对象转 JSON 串
     * @param obj 传入对象
     * @return JSON 串
     */
    public static String toJsonString(Object obj) {
        try {
            return JSON.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("Exception: {}, Message: {}, Time: {} " + "\r\n" + " StackTrace: [{}]", e.getClass(), e.getMessage(), DateUtil.now(), ExceptionUtil.stacktraceToString(e));
            throw new ProjectJsonException(ProjectExceptionCodeEnum.JSON_ERROR);
        }
    }

    /**
     * 对象转 JSON 字节
     * @param obj 传入对象
     * @return JSON 字节数组
     */
    public static byte[] toJsonBytes(Object obj) {
        try {
            return JSON.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            log.error("Exception: {}, Message: {}, Time: {} " + "\r\n" + " StackTrace: [{}]", e.getClass(), e.getMessage(), DateUtil.now(), ExceptionUtil.stacktraceToString(e));
            throw new ProjectJsonException(ProjectExceptionCodeEnum.JSON_ERROR);
        }
    }

    /**
     * JSON 字符串转 Java 对象
     * @param jsonStr JSON 串
     * @param classType 对象类型
     * @param <T> 返回对象
     * @return 转换后对象
     */
    public static <T> T toJavaBean(String jsonStr, Class<T> classType) {
        if (StrUtil.isBlank(jsonStr) || classType == null) {
            return null;
        }
        try {
            return JSON.readValue(jsonStr, classType);
        } catch (JsonProcessingException e) {
            log.error("Exception: {}, Message: {}, Time: {} " + "\r\n" + " StackTrace: [{}]", e.getClass(), e.getMessage(), DateUtil.now(), ExceptionUtil.stacktraceToString(e));
            throw new ProjectJsonException(ProjectExceptionCodeEnum.JSON_ERROR);
        }
    }


    /**
     * JSON 串转 Map
     * @param jsonStr JSON 串
     * @return Map
     */
    @SuppressWarnings("all")
    public static Map<String, Object> toMap(String jsonStr) {
        if (StrUtil.isBlank(jsonStr)) {
            return null;
        }
        try {
            return JSON.readValue(jsonStr, Map.class);
        } catch (JsonProcessingException e) {
            log.error("Exception: {}, Message: {}, Time: {} " + "\r\n" + " StackTrace: [{}]", e.getClass(), e.getMessage(), DateUtil.now(), ExceptionUtil.stacktraceToString(e));
            throw new ProjectJsonException(ProjectExceptionCodeEnum.TOKEN_INVALID);
        }
    }

}